<?php
abstract class Macys_Oauth_Authenticate_BaseAuth implements Zend_Auth_Adapter_Interface {

	protected $_client_id;
	protected $_secret;

	protected $_scope;

	protected $_authType = null;


	protected $_refresh;
	protected $_redirect_uri;

	protected $_auth_uri = "http://oauth.macys.com";

	// Mashery Service Uri for Token / refresh token / mobile
	protected $_mashery_uri = "http://api.macys.com";

	protected $_auth_endpoint = null;


	protected $_logout_url = "/logout";
	protected $log;


	/**
	 * List of query parameters that get automatically dropped when rebuilding
	 * the current URL.
	 */
	protected static $DROP_QUERY_PARAMS = array(
        'code',
        'access_token',
		'state',
		'scope',
		'response_type',
	'grant_type'
	);

	/**
	 * @param mixed $config - Zend_Config or array
	 */
	public function __construct($config) {
		$this->log = Zend_Registry::get('log');

		if($config instanceof Zend_Config) {
			$config = $config->toArray();
		}

		if(isset($config['auth_uri'])) {
			$this->_auth_uri = $config['auth_uri'];
			unset($config['auth_uri']);
		}


		if (isset($config['client_id'])) {
			$this->_client_id = $config['client_id'];
			unset($config['client_id']);
		} else {
			throw new Zend_Auth_Exception('Required param "client_id" is missing param in config');
		}

		if (isset($config['secret'])) {
			$this->_secret = $config['secret'];
			unset($config['secret']);
		} else {
			throw new Zend_Auth_Exception('Required param "secret" is missing param in config');
		}

		if (isset($config['redirect_uri'])) {
			$this->_redirect_uri = $config['redirect_uri'];
			unset($config['redirect_uri']);
		} else {
			$this->_redirect_uri = null;
		}

		if (isset($config['scope'])) {
			$this->_scope = $config['scope'];
			unset($config['scope']);
		} else {
			$this->_scope = '';
		}

		$this->setAuthType();
	}


	/**
	 * User Needs to Override this in class to specify what type of Auth
	 * derived call will work on
	 * @param string $type
	 */
	abstract protected function setAuthType($type=null);

	/**
	 * Redirect to Macys OAuth login page
	 */
	public function redirect()
	{
		$params = array(
            'scope'         => $this->_scope,
            'client_id'     => $this->_client_id,
		Macys_Constants::REDIRECT_URL  => $this->getRedirectUri(),
		Macys_Constants::RESPONSE_TYPE => $this->_authType,
		Macys_Constants::STATE => 'vi' . rand(5, 25000) . 'sa'
		);
		$url = $this->_auth_uri . $this->_auth_endpoint;
		$url .= '?';
		$url .= http_build_query($params, null, '&');
		$this->log->debug('Redirecting to OAuth URL : ' . $url);
		header('Location: '.$url);
		exit();
	}


	/**
	 * Performs the Logout from Macys
	 * User will be redirected to Macys Logout Page to remove his cookies & private data
	 * Not applicable for Application flows such as Mobile apps
	 */
	public function doLogout() {
		//Logout the User from Current application
		$auth = Zend_Auth::getInstance();
		$auth->clearIdentity();
		if(!empty($this->_authType)) {
			$params = array (
			Macys_Constants::CLIENTID => $this->_client_id,
			Macys_Constants::REDIRECT_URL => $this->getRedirectUri() ,
			Macys_Constants::SCOPE => $this->_scope,
			Macys_Constants::STATE => 'vi' . rand(25000, 50000) . 'sa'
			);
			$url = $this->_auth_uri . $this->_logout_url;
			$url .= '?' . http_build_query($params);
			$this->log->debug('Redirecting to Logout URL : ' . $url);
			header("Location: " . $url);
			exit();
		}
		// This will be used for Mobile type of auth
		return $this;
	}


	/**
	 * Make post to url with Client Id and Secret in Headers as Authroize params
	 * @param string $url
	 * @param array $params
	 * @return array
	 */
	protected function _apiCall($url, $params) {
		try {
			$client = new Macys_Base_HttpClient();
			$this->log->debug('Base Auth Calling Url : ' . $url);
			$client->setUri($url);
			$client->setCurlSupport();
			$client->setAuth($this->_client_id, $this->_secret);
			$client->setParameterPost($params);
			$client->setContentType();
			$client->setAcceptType();
			$client->request('POST');
			return $client->getResponseBodyArray();
		}
		catch (Exception $e) {
			$this->log->warn('Error Occured in _apiCall : ' . $e->getMessage());
		}
	}

	/**
	 * sets the User Zend_Auth Identity
	 * processes the response from Macys Auth
	 * @param Array $response
	 */
	protected function setAuthentication($response) {
		$checkAnyOneError = array('errorDetail','errorCode','error', 'error_description');
		$result = new Zend_Auth_Result(Zend_Auth_Result::FAILURE, false, array("User Not Authenticated"));
		$failed = false;
		foreach ($checkAnyOneError as $value) {
			if (isset($response[$value])) {
				$code = Zend_Auth_Result::FAILURE;
				$msgs[] = $response[$value];
				$result = new Zend_Auth_Result($code, false, $msgs);
				$failed = true;
			}
		}
		//var_dump($response); exit();
		if($failed == false) {
			if(is_array($response)) {
				foreach ($response as $key => $value) {
					$this->log->debug(' Response code : Key = ' . $key . ' = ' . $value);
				}
				if(isset($response['access_token'])) {
					$code = Zend_Auth_Result::SUCCESS;
					$identity = $response['access_token'];
					$result = new Zend_Auth_Result($code, $identity);
					// TODO token_type=bearer&expires_in
					// TODO
				}
				else {
					$code = Zend_Auth_Result::FAILURE;
					foreach ($response as $key => $value) {
						$msgs[] = $response[$key];
						$this->log->debug('BASE AUTH FAILURE : ' . $key . ' = ' . $value);
					}
					$result = new Zend_Auth_Result($code, false, $msgs);
				}
			}
			else {
				$this->log->crit('Auth Response Recieved is not Valid :');
				$this->log->crit('Response Value :' . $response);
			}
		}
		return $result;
	}

	/**
	 *Checks to see if _redirect_uri is set, if not return current URL
	 */
	protected function getRedirectUri()
	{
		if($this->_redirect_uri != null)
		return $this->_redirect_uri;
		else
		return $this->getCurrentUrl();
	}

	/**
	 *Public function to allow users to set _redirect_uri after constructing the adapter
	 */
	public function setRedirectUri($redirect_uri)
	{
		$this->_redirect_uri = $redirect_uri;
		return $this;
	}

	/**
	 * Returns the Current URL, stripping it of known Macys parameters that should
	 * not persist.
	 *
	 * @return String the current URL
	 */
	protected function getCurrentUrl()
	{
		$protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on'
		? 'https://'
		: 'http://';
		$currentUrl = $protocol . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
		$parts = parse_url($currentUrl);

		// drop known fb params
		$query = '';
		if (!empty($parts['query'])) {
			$params = array();
			parse_str($parts['query'], $params);
			foreach(self::$DROP_QUERY_PARAMS as $key) {
				unset($params[$key]);
			}
			if (!empty($params)) {
				$query = '?' . http_build_query($params, null, '&');
			}
		}

		// use port if non default
		$port =
		isset($parts['port']) &&
		(($protocol === 'http://' && $parts['port'] !== 80) ||
		($protocol === 'https://' && $parts['port'] !== 443))
		? ':' . $parts['port'] : '';

		// rebuild
		return $protocol . $parts['host'] . $port . $parts['path'] . $query;
	}


}